package com.zkt.subject.domain.handler.subject;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zkt.subject.common.enums.SubjectInfoOptionEnum;
import com.zkt.subject.common.enums.SubjectInfoTypeEnum;
import com.zkt.subject.domain.convert.SubjectMultipleConverter;
import com.zkt.subject.domain.entity.SubjectUserScore;
import com.zkt.subject.infra.entity.SubjectAnswerBO;
import com.zkt.subject.infra.entity.SubjectInfoBO;
import com.zkt.subject.domain.entity.SubjectOptionBO;
import com.zkt.subject.infra.basic.entity.SubjectMultiple;
import com.zkt.subject.infra.basic.service.ISubjectMultipleService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 赵开泰
 * @program jc-club
 * @date 2024/10/6
 * @description 多选题的策略类
 **/

@Component
public class MultipleTypeHandler implements SubjectTypeHandler {
	
	@Resource
	private ISubjectMultipleService subjectMultipleService;
	
	/**
	 * 枚举身份的识别
	 *
	 * @return 题目类型的枚举
	 */
	@Override
	public SubjectInfoTypeEnum getHandlerType() {
		return SubjectInfoTypeEnum.MULTIPLE;
	}
	
	/**
	 * 实际的题目的插入
	 *
	 * @param subjectInfoBO 题目数据
	 */
	@Override
	public void add(SubjectInfoBO subjectInfoBO) {
		if (ObjectUtil.isNull(subjectInfoBO.getOptionList())) {
			return;
		}
		
		// 多选题目的插入
		List<SubjectMultiple> subjectMultipleList = new LinkedList<>();
		subjectInfoBO.getOptionList().forEach(option -> {
			SubjectMultiple subjectMultiple = SubjectMultipleConverter.INSTANCE.convertBoToMultiple(option);
			subjectMultiple.setId(null);
			subjectMultiple.setSubjectId(subjectInfoBO.getId());
			subjectMultipleList.add(subjectMultiple);
		});
		subjectMultipleService.saveBatch(subjectMultipleList);
	}
	
	/**
	 * 实际的题目的删除
	 *
	 * @param subjectId 题目id
	 */
	@Override
	public void delete(Long subjectId) {
		if (subjectId != null) {
			subjectMultipleService.lambdaUpdate()
					.eq(SubjectMultiple::getSubjectId, subjectId)
					.remove();
		}
	}
	
	/**
	 * 实际的题目的更新
	 *
	 * @param subjectInfoBO 题目数据
	 */
	@Override
	public void update(SubjectInfoBO subjectInfoBO) {
		if (ObjUtil.isNull(subjectInfoBO.getId()) || CollUtil.isEmpty(subjectInfoBO.getOptionList())) {
			return;
		}
		
		this.delete(subjectInfoBO.getId());
		this.add(subjectInfoBO);
	}
	
	/**
	 * 根据题目id查询对应题目信息
	 *
	 * @param subjectId 题目id
	 * @return 题目信息
	 */
	@Override
	public SubjectOptionBO queryBySubjectId(Long subjectId) {
		List<SubjectMultiple> subjectMultipleList =
				subjectMultipleService.lambdaQuery().eq(SubjectMultiple::getSubjectId, subjectId).list();
		if (CollUtil.isEmpty(subjectMultipleList)) {
			return null;
		}
		SubjectOptionBO subjectOptionBO = new SubjectOptionBO();
		List<SubjectAnswerBO> subjectAnswerBOList = SubjectMultipleConverter.INSTANCE.convertListMultipleToBo(subjectMultipleList);
		subjectOptionBO.setOptionList(subjectAnswerBOList);
		return subjectOptionBO;
	}
	
	/**
	 * 获取用户得分
	 *
	 * @param subjectInfoBO 用户答案信息
	 * @return 用户得分
	 */
	@Override
	public SubjectUserScore getUserScore(SubjectInfoBO subjectInfoBO) {
		SubjectUserScore subjectUserScore = new SubjectUserScore();
		if (CollUtil.isEmpty(subjectInfoBO.getOptionList())) {
			return subjectUserScore;
		}
		
		List<SubjectAnswerBO> optionList = subjectInfoBO.getOptionList();
		String answer = optionList.stream()
				.map(SubjectAnswerBO::getOptionType)
				.sorted()
				.map(SubjectInfoOptionEnum::getByCode)
				.filter(ObjUtil::isNotNull)
				.collect(Collectors.joining("，"));
		subjectUserScore.setUserAnswer(answer);
		subjectUserScore.setUserScore(0);

// 获取正确选项列表
		List<SubjectMultiple> subjectMultipleList = subjectMultipleService.lambdaQuery()
				.eq(SubjectMultiple::getSubjectId, subjectInfoBO.getId())
				.eq(SubjectMultiple::getIsCorrect, 1)
				.list();
		
		Set<Integer> correctOptionSet = subjectMultipleList.stream()
				.map(SubjectMultiple::getOptionType)
				.collect(Collectors.toSet());
		
		Set<Integer> userOptionSet = optionList.stream()
				.map(SubjectAnswerBO::getOptionType)
				.collect(Collectors.toSet());

		// 判断是否选了错误项
		for (Integer userOption : userOptionSet) {
			if (!correctOptionSet.contains(userOption)) {
				// 用户选了不该选的
				subjectUserScore.setUserScore(0);
				return subjectUserScore;
			}
		}

// 判断是否全对
		if (userOptionSet.size() == correctOptionSet.size()) {
			subjectUserScore.setUserScore(subjectInfoBO.getSubjectScore()); // 满分
		} else if (userOptionSet.size() < correctOptionSet.size() && !userOptionSet.isEmpty()) {
			subjectUserScore.setUserScore(subjectInfoBO.getSubjectScore() / 2); // 半分
		} else {
			subjectUserScore.setUserScore(0);
		}
		
		return subjectUserScore;
	}
}
